package org.wesc.boot.common.utils;

import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author Wesley Cheung
 * @date 2018/8/24 17:06
 */
@Slf4j
public class CopyUtil {

    /**
     * 将父类的属性全部(serialVersionUID排除)拷贝到子类中
     *
     * @param parent 父类
     * @param child 子类
     */
    public static void copyParentToChild(Object parent, Object child) {
        if (child.getClass().getSuperclass() != parent.getClass()) {
            log.error("child不是parent的子类");
            return;
        }
        Class<?> fatherClass = parent.getClass();
        Field[] declaredFields = fatherClass.getDeclaredFields();
        for (Field field : declaredFields) {
            if ("serialVersionUID".equals(field.getName())) {
                continue;
            }
            // 屏蔽首字母为大写的字段
            if (Character.isUpperCase(field.getName().substring(0, 1).charAt(0))) {
                continue;
            }
            try {
                Method method = fatherClass.getMethod("get" + upperHeadChar(field.getName()));
                Object obj = method.invoke(parent);
                field.setAccessible(true);
                field.set(child, obj);
            } catch (SecurityException | IllegalArgumentException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 首字母大写，in:deleteDate，out:DeleteDate
     */
    private static String upperHeadChar(String in) {
        String head = in.substring(0, 1);
        return head.toUpperCase() + in.substring(1);
    }


    /**
     * 深复制
     */
    public static <T extends Serializable> T deepCopy(T t) {
        T cloneObj = null;
        try {
            //写入字节流
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ObjectOutputStream obs = new ObjectOutputStream(out);
            obs.writeObject(t);
            obs.close();

            //分配内存，写入原始对象，生成新对象
            ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(ios);
            //返回生成的新对象
            cloneObj = (T) ois.readObject();
            ois.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cloneObj;
    }
}
